/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package DAO.Financial;

import DAO.exceptions.IllegalOrphanException;
import DAO.exceptions.NonexistentEntityException;
import DAO.exceptions.PreexistingEntityException;
import FinancialEntity.Date;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import FinancialEntity.Quote;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

/**
 *
 * @author Sebastian
 */
public class DateDAO implements Serializable, DAOFinancial {
    
    public void create(Date date, EntityManager em) throws PreexistingEntityException, Exception {
        if (date.getQuoteList() == null) {
            date.setQuoteList(new ArrayList<Quote>());
        }
        try {
            List<Quote> attachedQuoteList = new ArrayList<Quote>();
            for (Quote quoteListQuoteToAttach : date.getQuoteList()) {
                quoteListQuoteToAttach = em.getReference(quoteListQuoteToAttach.getClass(), quoteListQuoteToAttach.getQuotePK());
                attachedQuoteList.add(quoteListQuoteToAttach);
            }
            date.setQuoteList(attachedQuoteList);
            em.persist(date);
            for (Quote quoteListQuote : date.getQuoteList()) {
                Date oldDateidOfQuoteListQuote = quoteListQuote.getDateid();
                quoteListQuote.setDateid(date);
                quoteListQuote = em.merge(quoteListQuote);
                if (oldDateidOfQuoteListQuote != null) {
                    oldDateidOfQuoteListQuote.getQuoteList().remove(quoteListQuote);
                    oldDateidOfQuoteListQuote = em.merge(oldDateidOfQuoteListQuote);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findDate(date.getId(), em) != null) {
                throw new PreexistingEntityException("Date " + date + " already exists.", ex);
            }
            throw ex;
        } 
    }

    public void edit(Date date, EntityManager em) throws IllegalOrphanException, NonexistentEntityException, Exception {
        try {
            Date persistentDate = em.find(Date.class, date.getId());
            List<Quote> quoteListOld = persistentDate.getQuoteList();
            List<Quote> quoteListNew = date.getQuoteList();
            List<String> illegalOrphanMessages = null;
            for (Quote quoteListOldQuote : quoteListOld) {
                if (!quoteListNew.contains(quoteListOldQuote)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Quote " + quoteListOldQuote + " since its dateid field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            List<Quote> attachedQuoteListNew = new ArrayList<Quote>();
            for (Quote quoteListNewQuoteToAttach : quoteListNew) {
                quoteListNewQuoteToAttach = em.getReference(quoteListNewQuoteToAttach.getClass(), quoteListNewQuoteToAttach.getQuotePK());
                attachedQuoteListNew.add(quoteListNewQuoteToAttach);
            }
            quoteListNew = attachedQuoteListNew;
            date.setQuoteList(quoteListNew);
            date = em.merge(date);
            for (Quote quoteListNewQuote : quoteListNew) {
                if (!quoteListOld.contains(quoteListNewQuote)) {
                    Date oldDateidOfQuoteListNewQuote = quoteListNewQuote.getDateid();
                    quoteListNewQuote.setDateid(date);
                    quoteListNewQuote = em.merge(quoteListNewQuote);
                    if (oldDateidOfQuoteListNewQuote != null && !oldDateidOfQuoteListNewQuote.equals(date)) {
                        oldDateidOfQuoteListNewQuote.getQuoteList().remove(quoteListNewQuote);
                        oldDateidOfQuoteListNewQuote = em.merge(oldDateidOfQuoteListNewQuote);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = date.getId();
                if (findDate(id, em) == null) {
                    throw new NonexistentEntityException("The date with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } 
    }

    public void destroy(Integer id, EntityManager em) throws IllegalOrphanException, NonexistentEntityException {
            Date date;
            try {
                date = em.getReference(Date.class, id);
                date.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The date with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<Quote> quoteListOrphanCheck = date.getQuoteList();
            for (Quote quoteListOrphanCheckQuote : quoteListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Date (" + date + ") cannot be destroyed since the Quote " + quoteListOrphanCheckQuote + " in its quoteList field has a non-nullable dateid field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            em.remove(date);
    }

    public List<Date> findDateEntities(EntityManager em) {
        return findDateEntities(true, -1, -1, em);
    }

    public List<Date> findDateEntities(int maxResults, int firstResult, EntityManager em) {
        return findDateEntities(false, maxResults, firstResult, em);
    }

    private List<Date> findDateEntities(boolean all, int maxResults, int firstResult, EntityManager em) {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Date.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList(); 
    }

    public Date findDate(Integer id, EntityManager em) {
            return em.find(Date.class, id);
    }

    public int getDateCount(EntityManager em) {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Date> rt = cq.from(Date.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
    }
    
}
